﻿//// <file>
////     <copyright see="prj:///doc/copyright.txt"/>
////     <license see="prj:///doc/license.txt"/>
////     <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
////     <version>$Revision: 3279 $</version>
//// </file>

//using System;
//using System.Collections.Generic;
//using System.Drawing;
//using System.Diagnostics;
//using System.Runtime.InteropServices;

//using ICSharpCode.TextEditor.Document;

//namespace ICSharpCode.TextEditor
//{
//	/// <summary>
//	/// In this enumeration are all caret modes listed.
//	/// </summary>
//	public enum CaretMode {
//		/// <summary>
//		/// If the caret is in insert mode typed characters will be
//		/// inserted at the caret position
//		/// </summary>
//		InsertMode,
		
//		/// <summary>
//		/// If the caret is in overwirte mode typed characters will
//		/// overwrite the character at the caret position
//		/// </summary>
//		OverwriteMode
//	}
	
	
//	public class Caret : System.IDisposable
//	{
//		int       line          = 0;
//		int       column        = 0;
//		int       desiredXPos   = 0;
//		CaretMode caretMode;
		
//		static bool     caretCreated = false;
//		bool     hidden       = true;
//		TextArea textArea;
//		Point    currentPos   = new Point(-1, -1);
//		Ime      ime          = null;
//		CaretImplementation caretImplementation;
		
//		/// <value>
//		/// The 'prefered' xPos in which the caret moves, when it is moved
//		/// up/down. Measured in pixels, not in characters!
//		/// </value>
//		public int DesiredColumn {
//			get {
//				return desiredXPos;
//			}
//			set {
//				desiredXPos = value;
//			}
//		}
		
//		/// <value>
//		/// The current caret mode.
//		/// </value>
//		public CaretMode CaretMode {
//			get {
//				return caretMode;
//			}
//			set {
//				caretMode = value;
//				OnCaretModeChanged(EventArgs.Empty);
//			}
//		}
		
//		public int Line {
//			get {
//				return line;
//			}
//			set {
//				line = value;
//				ValidateCaretPos();
//				UpdateCaretPosition();
//				OnPositionChanged(EventArgs.Empty);
//			}
//		}
		
//		public int Column {
//			get {
//				return column;
//			}
//			set {
//				column = value;
//				ValidateCaretPos();
//				UpdateCaretPosition();
//				OnPositionChanged(EventArgs.Empty);
//			}
//		}
		
//		public TextLocation Position {
//			get {
//				return new TextLocation(column, line);
//			}
//			set {
//				line   = value.Y;
//				column = value.X;
//				ValidateCaretPos();
//				UpdateCaretPosition();
//				OnPositionChanged(EventArgs.Empty);
//			}
//		}
		
//		public int Offset {
//			get {
//				return textArea.Document.PositionToOffset(Position);
//			}
//		}
		
//		public Caret(TextArea textArea)
//		{
//			this.textArea = textArea;
//			textArea.GotFocus  += new EventHandler(GotFocus);
//			textArea.LostFocus += new EventHandler(LostFocus);
//			if (Environment.OSVersion.Platform == PlatformID.Unix)
//				caretImplementation = new ManagedCaret(this);
//			else
//				caretImplementation = new Win32Caret(this);
//		}
		
//		public void Dispose()
//		{
//			textArea.GotFocus  -= new EventHandler(GotFocus);
//			textArea.LostFocus -= new EventHandler(LostFocus);
//			textArea = null;
//			caretImplementation.Dispose();
//		}
		
//		public TextLocation ValidatePosition(TextLocation pos)
//		{
//			int line   = Math.Max(0, Math.Min(textArea.Document.TotalNumberOfLines - 1, pos.Y));
//			int column = Math.Max(0, pos.X);
			
//			if (column == int.MaxValue || !textArea.TextEditorProperties.AllowCaretBeyondEOL) {
//				LineSegment lineSegment = textArea.Document.GetLineSegment(line);
//				column = Math.Min(column, lineSegment.Length);
//			}
//			return new TextLocation(column, line);
//		}
		
//		/// <remarks>
//		/// If the caret position is outside the document text bounds
//		/// it is set to the correct position by calling ValidateCaretPos.
//		/// </remarks>
//		public void ValidateCaretPos()
//		{
//			line = Math.Max(0, Math.Min(textArea.Document.TotalNumberOfLines - 1, line));
//			column = Math.Max(0, column);
			
//			if (column == int.MaxValue || !textArea.TextEditorProperties.AllowCaretBeyondEOL) {
//				LineSegment lineSegment = textArea.Document.GetLineSegment(line);
//				column = Math.Min(column, lineSegment.Length);
//			}
//		}
		
//		void CreateCaret()
//		{
//			while (!caretCreated) {
//				switch (caretMode) {
//					case CaretMode.InsertMode:
//						caretCreated = caretImplementation.Create(2, textArea.TextView.FontHeight);
//						break;
//					case CaretMode.OverwriteMode:
//						caretCreated = caretImplementation.Create((int)textArea.TextView.SpaceWidth, textArea.TextView.FontHeight);
//						break;
//				}
//			}
//			if (currentPos.X  < 0) {
//				ValidateCaretPos();
//				currentPos = ScreenPosition;
//			}
//			caretImplementation.SetPosition(currentPos.X, currentPos.Y);
//			caretImplementation.Show();
//		}
		
//		public void RecreateCaret()
//		{
//			Log("RecreateCaret");
//			DisposeCaret();
//			if (!hidden) {
//				CreateCaret();
//			}
//		}
		
//		void DisposeCaret()
//		{
//			if (caretCreated) {
//				caretCreated = false;
//				caretImplementation.Hide();
//				caretImplementation.Destroy();
//			}
//		}
		
//		void GotFocus(object sender, EventArgs e)
//		{
//			Log("GotFocus, IsInUpdate=" + textArea.MotherTextEditorControl.IsInUpdate);
//			hidden = false;
//			if (!textArea.MotherTextEditorControl.IsInUpdate) {
//				CreateCaret();
//				UpdateCaretPosition();
//			}
//		}
		
//		void LostFocus(object sender, EventArgs e)
//		{
//			Log("LostFocus");
//			hidden = true;
//			DisposeCaret();
//		}
		
//		public Point ScreenPosition {
//			get {
//				int xpos = textArea.TextView.GetDrawingXPos(this.line, this.column);
//				return new Point(textArea.TextView.DrawingPosition.X + xpos,
//				                 textArea.TextView.DrawingPosition.Y
//				                 + (textArea.Document.GetVisibleLine(this.line)) * textArea.TextView.FontHeight
//				                 - textArea.TextView.TextArea.VirtualTop.Y);
//			}
//		}
//		int oldLine = -1;
//		bool outstandingUpdate;
		
//		internal void OnEndUpdate()
//		{
//			if (outstandingUpdate)
//				UpdateCaretPosition();
//		}
		
//		public void UpdateCaretPosition()
//		{
//			Log("UpdateCaretPosition");
			
//			if (caretImplementation.RequireRedrawOnPositionChange) {
//				textArea.UpdateLine(oldLine);
//				if (line != oldLine)
//					textArea.UpdateLine(line);
//			} else {
//				if (textArea.MotherTextAreaControl.TextEditorProperties.LineViewerStyle == LineViewerStyle.FullRow && oldLine != line) {
//					textArea.UpdateLine(oldLine);
//					textArea.UpdateLine(line);
//				}
//			}
//			oldLine = line;
			
			
//			if (hidden || textArea.MotherTextEditorControl.IsInUpdate) {
//				outstandingUpdate = true;
//				return;
//			} else {
//				outstandingUpdate = false;
//			}
//			ValidateCaretPos();
//			int lineNr = this.line;
//			int xpos = textArea.TextView.GetDrawingXPos(lineNr, this.column);
//			//LineSegment lineSegment = textArea.Document.GetLineSegment(lineNr);
//			Point pos = ScreenPosition;
//			if (xpos >= 0) {
//				CreateCaret();
//				bool success = caretImplementation.SetPosition(pos.X, pos.Y);
//				if (!success) {
//					caretImplementation.Destroy();
//					caretCreated = false;
//					UpdateCaretPosition();
//				}
//			} else {
//				caretImplementation.Destroy();
//			}
			
//			// set the input method editor location
//			if (ime == null) {
//				ime = new Ime(textArea.Handle, textArea.Document.TextEditorProperties.Font);
//			} else {
//				ime.HWnd = textArea.Handle;
//				ime.Font = textArea.Document.TextEditorProperties.Font;
//			}
//			ime.SetIMEWindowLocation(pos.X, pos.Y);
			
//			currentPos = pos;
//		}
		
//		[Conditional("DEBUG")]
//		static void Log(string text)
//		{
//			//Console.WriteLine(text);
//		}
		
//		#region Caret implementation
//		internal void PaintCaret(Graphics g)
//		{
//			caretImplementation.PaintCaret(g);
//		}
		
//		abstract class CaretImplementation : IDisposable
//		{
//			public bool RequireRedrawOnPositionChange;
			
//			public abstract bool Create(int width, int height);
//			public abstract void Hide();
//			public abstract void Show();
//			public abstract bool SetPosition(int x, int y);
//			public abstract void PaintCaret(Graphics g);
//			public abstract void Destroy();
			
//			public virtual void Dispose()
//			{
//				Destroy();
//			}
//		}
		
//		class ManagedCaret : CaretImplementation
//		{
//			System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer { Interval = 300 };
//			bool visible;
//			bool blink = true;
//			int x, y, width, height;
//			TextArea textArea;
//			Caret parentCaret;
			
//			public ManagedCaret(Caret caret)
//			{
//				base.RequireRedrawOnPositionChange = true;
//				this.textArea = caret.textArea;
//				this.parentCaret = caret;
//				timer.Tick += CaretTimerTick;
//			}
			
//			void CaretTimerTick(object sender, EventArgs e)
//			{
//				blink = !blink;
//				if (visible)
//					textArea.UpdateLine(parentCaret.Line);
//			}
			
//			public override bool Create(int width, int height)
//			{
//				this.visible = true;
//				this.width = width - 2;
//				this.height = height;
//				timer.Enabled = true;
//				return true;
//			}
//			public override void Hide()
//			{
//				visible = false;
//			}
//			public override void Show()
//			{
//				visible = true;
//			}
//			public override bool SetPosition(int x, int y)
//			{
//				this.x = x - 1;
//				this.y = y;
//				return true;
//			}
//			public override void PaintCaret(Graphics g)
//			{
//				if (visible && blink)
//					g.DrawRectangle(Pens.Gray, x, y, width, height);
//			}
//			public override void Destroy()
//			{
//				visible = false;
//				timer.Enabled = false;
//			}
//			public override void Dispose()
//			{
//				base.Dispose();
//				timer.Dispose();
//			}
//		}
		
//		class Win32Caret : CaretImplementation
//		{
//			[DllImport("User32.dll")]
//			static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight);
			
//			[DllImport("User32.dll")]
//			static extern bool SetCaretPos(int x, int y);
			
//			[DllImport("User32.dll")]
//			static extern bool DestroyCaret();
			
//			[DllImport("User32.dll")]
//			static extern bool ShowCaret(IntPtr hWnd);
			
//			[DllImport("User32.dll")]
//			static extern bool HideCaret(IntPtr hWnd);
			
//			TextArea textArea;
			
//			public Win32Caret(Caret caret)
//			{
//				this.textArea = caret.textArea;
//			}
			
//			public override bool Create(int width, int height)
//			{
//				return CreateCaret(textArea.Handle, 0, width, height);
//			}
//			public override void Hide()
//			{
//				HideCaret(textArea.Handle);
//			}
//			public override void Show()
//			{
//				ShowCaret(textArea.Handle);
//			}
//			public override bool SetPosition(int x, int y)
//			{
//				return SetCaretPos(x, y);
//			}
//			public override void PaintCaret(Graphics g)
//			{
//			}
//			public override void Destroy()
//			{
//				DestroyCaret();
//			}
//		}
//		#endregion
		
//		bool firePositionChangedAfterUpdateEnd;
		
//		void FirePositionChangedAfterUpdateEnd(object sender, EventArgs e)
//		{
//			OnPositionChanged(EventArgs.Empty);
//		}
		
//		protected virtual void OnPositionChanged(EventArgs e)
//		{
//			if (this.textArea.MotherTextEditorControl.IsInUpdate) {
//				if (firePositionChangedAfterUpdateEnd == false) {
//					firePositionChangedAfterUpdateEnd = true;
//					this.textArea.Document.UpdateCommited += FirePositionChangedAfterUpdateEnd;
//				}
//				return;
//			} else if (firePositionChangedAfterUpdateEnd) {
//				this.textArea.Document.UpdateCommited -= FirePositionChangedAfterUpdateEnd;
//				firePositionChangedAfterUpdateEnd = false;
//			}
			
//			List<FoldMarker> foldings = textArea.Document.FoldingManager.GetFoldingsFromPosition(line, column);
//			bool  shouldUpdate = false;
//			foreach (FoldMarker foldMarker in foldings) {
//				shouldUpdate |= foldMarker.IsFolded;
//				foldMarker.IsFolded = false;
//			}
			
//			if (shouldUpdate) {
//				textArea.Document.FoldingManager.NotifyFoldingsChanged(EventArgs.Empty);
//			}
			
//			if (PositionChanged != null) {
//				PositionChanged(this, e);
//			}
//			textArea.ScrollToCaret();
//		}
		
//		protected virtual void OnCaretModeChanged(EventArgs e)
//		{
//			if (CaretModeChanged != null) {
//				CaretModeChanged(this, e);
//			}
//			caretImplementation.Hide();
//			caretImplementation.Destroy();
//			caretCreated = false;
//			CreateCaret();
//			caretImplementation.Show();
//		}
		
//		/// <remarks>
//		/// Is called each time the caret is moved.
//		/// </remarks>
//		public event EventHandler PositionChanged;
		
//		/// <remarks>
//		/// Is called each time the CaretMode has changed.
//		/// </remarks>
//		public event EventHandler CaretModeChanged;
//	}
//}
